package com.anti.modular.bus.houselease.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.anti.commom.core.utils.DecimalUtils;
import com.anti.core.context.login.LoginContextHolder;
import com.anti.core.utils.IdFlowingUtil;
import com.anti.jdbc.DBUtils;
import com.anti.jdbc.support.page.PageParam;
import com.anti.jdbc.support.page.PageResult;
import com.anti.commom.core.exception.BusinessException;
import com.anti.modular.bus.billrentadjustment.entity.BillRentAdjustment;
import com.anti.modular.bus.billrentadjustment.param.BillRentAdjustmentParam;
import com.anti.modular.bus.billrentadjustment.service.BillRentAdjustmentService;
import com.anti.modular.bus.busbasicsettings.entity.BusBasicSettings;
import com.anti.modular.bus.busbasicsettings.service.BusBasicSettingsService;
import com.anti.modular.bus.busroom.entity.BusRoom;
import com.anti.modular.bus.busroom.param.BusRoomParam;
import com.anti.modular.bus.busroom.service.BusRoomService;
import com.anti.modular.bus.housebill.entity.HouseBill;
import com.anti.modular.bus.housebill.service.HouseBillService;
import com.anti.modular.bus.housebilldetail.entity.HouseBillDetail;
import com.anti.modular.bus.housebilldetail.service.HouseBillDetailService;
import com.anti.modular.bus.houselease.entity.HouseLease;
import com.anti.modular.bus.houselease.enums.HouseLeaseExceptionEnum;
import com.anti.modular.bus.houselease.param.HouseLeaseParam;
import com.anti.modular.bus.houselease.param.HouseLeaseParam2;
import com.anti.modular.bus.houselease.param.HouseLeaseTzParam;
import com.anti.modular.bus.houselease.result.HouseLeaseResult;
import com.anti.modular.bus.houselease.result.LeaseFurnitureShResult;
import com.anti.modular.bus.houselease.result.TjSysRes;
import com.anti.modular.bus.houselease.result.excel.*;
import com.anti.modular.bus.houselease.service.HouseLeaseService;
import com.anti.modular.bus.houselease.vo.DayCompare;
import com.anti.modular.bus.houselease.vo.TimeVo;
import com.anti.modular.bus.houseleaselive.entity.HouseLeaseLive;
import com.anti.modular.bus.houseleaselive.service.HouseLeaseLiveService;
import com.anti.modular.bus.hydropowermeter.param.HydropowerMeterParam;
import com.anti.modular.bus.hydropowermeter.service.HydropowerMeterService;
import com.anti.modular.bus.roomdeposit.entity.LeaseDeposit;
import com.anti.modular.bus.roomdeposit.entity.RoomDeposit;
import com.anti.modular.bus.roomdeposit.result.LeaseDepositResult;
import com.anti.modular.bus.roomdeposit.result.RoomDepositResult;
import com.anti.modular.bus.roomdeposit.service.LeaseDepositService;
import com.anti.modular.bus.roomdeposit.service.RoomDepositService;
import com.anti.modular.bus.roomexpenses.entity.LeaseExpenses;
import com.anti.modular.bus.roomexpenses.entity.RoomExpenses;
import com.anti.modular.bus.roomexpenses.result.RoomExpensesResult;
import com.anti.modular.bus.roomexpenses.service.LeaseExpensesService;
import com.anti.modular.bus.roomexpenses.service.RoomExpensesService;
import com.anti.modular.bus.roomfurniture.entity.LeaseFurniture;
import com.anti.modular.bus.roomfurniture.entity.RoomFurniture;
import com.anti.modular.bus.roomfurniture.result.RoomFurnitureResult;
import com.anti.modular.bus.roomfurniture.service.LeaseFurnitureService;
import com.anti.modular.bus.roomfurniture.service.RoomFurnitureService;
import com.anti.modular.bus.roomreservation.entity.RoomReservation;
import com.anti.modular.bus.roomreservation.service.RoomReservationService;
import com.anti.modular.commonutils.CalculateQs;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 房间租约service接口实现类
 *
 * @author anti
 * @date 2021-05-06 09:30:21
 */
@Service
public class HouseLeaseServiceImpl implements HouseLeaseService {
    @Resource
    DBUtils dbUtils;
    @Resource
    HouseLeaseLiveService houseLeaseLiveService;
    @Resource
    HouseBillService houseBillService;
    @Resource
    HouseBillDetailService houseBillDetailService;
    @Resource
    BusRoomService busRoomService;
    @Resource
    RoomDepositService roomDepositService;
    @Resource
    RoomExpensesService roomExpensesService;
    @Resource
    BusBasicSettingsService busBasicSettingsService;
    @Resource
    RoomFurnitureService roomFurnitureService;
    @Resource
    BillRentAdjustmentService billRentAdjustmentService;
    @Resource
    HydropowerMeterService hydropowerMeterService;

    @Resource
    LeaseDepositService leaseDepositService;
    @Resource
    LeaseExpensesService leaseExpensesService;
    @Resource
    LeaseFurnitureService leaseFurnitureService;
    @Resource
    RoomReservationService roomReservationService;

    @Override
    public HouseLease getById(HouseLeaseParam houseLeaseParam){
        String sql="select * from house_lease where id =? ";
        return dbUtils.get(sql,HouseLease.class,houseLeaseParam.getId());
    }

    @Override
    public HouseLease getByLeaseId(Long id) {
        String sql="select * from house_lease where id =? ";
        return dbUtils.get(sql,HouseLease.class,id);
    }

    @Override
    public PageResult page(PageParam pageParam,HouseLeaseParam houseLeaseParam) {
        StringBuilder sb=new StringBuilder("select * from house_lease where 1=1 and status =0 ");
        ArrayList<Object> param = CollectionUtil.newArrayList();
        if (ObjectUtil.isNotNull(houseLeaseParam)) {
            if (ObjectUtil.isNotEmpty(houseLeaseParam.getType())) {
                if (houseLeaseParam.getType()==1){
                    sb.append(" and lease_status <> 2");
                    if (ObjectUtil.isNotEmpty(houseLeaseParam.getNumType())) {
                        int numType = houseLeaseParam.getNumType();
                        if (1==numType){
                            //七日内到期
                            sb.append(" and rent_end_date >= DATE_FORMAT(DATE_ADD(NOW(),INTERVAL -7 DAY),'%Y-%m-%d') and rent_end_date <=DATE_FORMAT(NOW(),'%Y-%m-%d')");
                        }else if (2==numType){
                            sb.append(" and DATE_FORMAT(rent_end_date,'%Y-%m-%d') <=DATE_FORMAT(NOW(),'%Y-%m-%d')");
                        }
                    }
                }else {
                    sb.append(" and lease_status = 2");
                }
            }
            if (ObjectUtil.isNotEmpty(houseLeaseParam.getSearchType())&&ObjectUtil.isNotEmpty(houseLeaseParam.getSearchValue())) {
                String searchType = houseLeaseParam.getSearchType();
                if ("1".equals(searchType)){
                    sb.append(" and  room_name like  ? ");
                    param.add("%"+houseLeaseParam.getSearchValue()+"%");
                }
                if ("2".equals(searchType)){
                    sb.append(" and  room_name like  ? ");
                    param.add("%"+houseLeaseParam.getSearchValue()+"%");
                }
                if ("3".equals(searchType)){
                    sb.append(" and  name like  ? ");
                    param.add("%"+houseLeaseParam.getSearchValue()+"%");
                }
                if ("4".equals(searchType)){
                    sb.append(" and  phone =? ");
                    param.add(houseLeaseParam.getSearchValue());
                }
                if ("5".equals(searchType)){
                    sb.append(" and  id_card =  ? ");
                    param.add(houseLeaseParam.getSearchValue());
                }
            }
        }
        return dbUtils.query(pageParam,sb.toString(),param.toArray());
    }
    @Override
    public TjSysRes getTjSys(HouseLeaseParam houseLeaseParam) {
        StringBuilder sb=new StringBuilder("");
        if (ObjectUtil.isNotEmpty(houseLeaseParam.getSearchType())&&ObjectUtil.isNotEmpty(houseLeaseParam.getSearchValue())) {
            String searchType = houseLeaseParam.getSearchType();
            if ("1".equals(searchType)){
                sb.append(" and  room_name like  '%"+houseLeaseParam.getSearchValue()+"%' ");
            }
            if ("2".equals(searchType)){
                sb.append(" and  room_name like  '%"+houseLeaseParam.getSearchValue()+"%' ");
            }
            if ("3".equals(searchType)){
                sb.append(" and  name like  '%"+houseLeaseParam.getSearchValue()+"%' ");
            }
            if ("4".equals(searchType)){
                sb.append(" and  phone ='"+houseLeaseParam.getSearchValue()+"' ");
            }
            if ("5".equals(searchType)){
                sb.append(" and  id_card ='"+houseLeaseParam.getSearchValue()+"' ");
            }
        }
        StringBuilder sbMain=new StringBuilder("select (select count(*) from house_lease where status =0 and lease_status <> 2 "+sb.toString()+") as alls," +
                " (select count(*) from house_lease where status =0 and lease_status <> 2 and rent_end_date >= DATE_FORMAT(DATE_ADD(NOW(),INTERVAL -7 DAY),'%Y-%m-%d') and rent_end_date <=DATE_FORMAT(NOW(),'%Y-%m-%d') "+sb.toString()+") as dqrn," +
                "(select count(*) from house_lease where status =0 and lease_status <> 2  and DATE_FORMAT(rent_end_date,'%Y-%m-%d') <=DATE_FORMAT(NOW(),'%Y-%m-%d') "+sb.toString()+") as ydq from dual");
        return dbUtils.getFirst(sbMain.toString(),TjSysRes.class);
    }

    @Override
    public List<LeaseExcel> getExportData(HouseLeaseParam houseLeaseParam) {
        StringBuilder sb=new StringBuilder("select (select name from bus_real_estate where id = (select estateid from bus_room where id = a.room_id)) as state_name,\n" +
                "(select code from bus_room where id = a.room_id) as room_namet,a.*  from house_lease a where a.status =0 ");
        ArrayList<Object> param = CollectionUtil.newArrayList();
        if (ObjectUtil.isNotNull(houseLeaseParam)) {
            if (ObjectUtil.isNotEmpty(houseLeaseParam.getType())) {
                if (houseLeaseParam.getType()==1){
                    sb.append(" and lease_status <> 2");
                    if (ObjectUtil.isNotEmpty(houseLeaseParam.getNumType())) {
                        int numType = houseLeaseParam.getNumType();
                        if (1==numType){
                            //七日内到期
                            sb.append(" and rent_end_date >= DATE_FORMAT(DATE_ADD(NOW(),INTERVAL -7 DAY),'%Y-%m-%d') and rent_end_date <=DATE_FORMAT(NOW(),'%Y-%m-%d')");
                        }else if (2==numType){
                            sb.append(" and DATE_FORMAT(rent_end_date,'%Y-%m-%d') <=DATE_FORMAT(NOW(),'%Y-%m-%d')");
                        }
                    }
                }else {
                    sb.append(" and lease_status = 2");
                }
            }
            if (ObjectUtil.isNotEmpty(houseLeaseParam.getSearchType())&&ObjectUtil.isNotEmpty(houseLeaseParam.getSearchValue())) {
                String searchType = houseLeaseParam.getSearchType();
                if ("1".equals(searchType)){
                    sb.append(" and  room_name like  ? ");
                    param.add("%"+houseLeaseParam.getSearchValue()+"%");
                }
                if ("2".equals(searchType)){
                    sb.append(" and  room_name like  ? ");
                    param.add("%"+houseLeaseParam.getSearchValue()+"%");
                }
                if ("3".equals(searchType)){
                    sb.append(" and  name like  ? ");
                    param.add("%"+houseLeaseParam.getSearchValue()+"%");
                }
                if ("4".equals(searchType)){
                    sb.append(" and  phone =? ");
                    param.add(houseLeaseParam.getSearchValue());
                }
                if ("5".equals(searchType)){
                    sb.append(" and  id_card =  ? ");
                    param.add(houseLeaseParam.getSearchValue());
                }
            }
        }
        List<LeaseExcel> leaseExcels = dbUtils.query(sb.toString(), LeaseExcel.class, param.toArray());
        List<Long> ids = leaseExcels.stream().map(item -> item.getId()).collect(Collectors.toList());
        if (ids.size()>0){
            HashMap<String, Object> params = CollectionUtil.newHashMap();
            params.put("ids",ids);
            String tzrSql="select * from house_lease_live where status=0 and lease_id in (:ids)";
            List<LeaseLiveExcel> leaseLiveExcels = dbUtils.query(tzrSql, LeaseLiveExcel.class, params);
            String adjustSql="select * from bill_rent_adjustment where status=0 and lease_id in (:ids)";
            List<RentAdjustmentExcel> adjustmentExcels = dbUtils.query(adjustSql, RentAdjustmentExcel.class, params);
            String depositSql="select * from bus_lease_deposit where status=0 and lease_id in (:ids)";
            List<LeaseDepositExcel> leaseDepositExcels = dbUtils.query(depositSql, LeaseDepositExcel.class, params);
            String expensesSql="select * from bus_lease_expenses where status=0 and lease_id in (:ids)";
            List<LeaseExpensesExcel> leaseExpensesExcels = dbUtils.query(expensesSql, LeaseExpensesExcel.class, params);
            String furnitureSql="select * from bus_lease_furniture where status=0 and lease_id in (:ids)";
            List<LeaseFurnitureExcel> leaseFurnitureExcels = dbUtils.query(furnitureSql, LeaseFurnitureExcel.class, params);
            for (int i = 0; i < leaseExcels.size(); i++) {
                LeaseExcel leaseExcel = leaseExcels.get(i);
                List<LeaseLiveExcel> liveExcels = leaseLiveExcels.stream().filter(item -> item.getLeaseId().equals(leaseExcel.getId())).collect(Collectors.toList());
                leaseExcel.setLeaseLiveExcels(liveExcels);
                List<RentAdjustmentExcel> adjustmentExcelList = adjustmentExcels.stream().filter(item -> item.getLeaseId().equals(leaseExcel.getId())).collect(Collectors.toList());
                leaseExcel.setRentAdjustmentExcels(adjustmentExcelList);
                List<LeaseDepositExcel> depositExcels = leaseDepositExcels.stream().filter(item -> item.getLeaseId().equals(leaseExcel.getId())).collect(Collectors.toList());
                leaseExcel.setLeaseDepositExcels(depositExcels);
                List<LeaseExpensesExcel> expensesExcels = leaseExpensesExcels.stream().filter(item -> item.getLeaseId().equals(leaseExcel.getId())).collect(Collectors.toList());
                leaseExcel.setLeaseExpensesExcels(expensesExcels);
                List<LeaseFurnitureExcel> furnitureExcels = leaseFurnitureExcels.stream().filter(item -> item.getLeaseId().equals(leaseExcel.getId())).collect(Collectors.toList());
                leaseExcel.setLeaseFurnitureExcels(furnitureExcels);
            }
        }
        return leaseExcels;
    }

    @Override
    public List<HouseLease> list(HouseLeaseParam houseLeaseParam) {
        String sql="";
        return dbUtils.query(sql,HouseLease.class);
    }

    @Override
    public List<LeaseFurnitureShResult> getLeaseFurnitureList(Long id) {
        String sql="select * from bus_lease_furniture where lease_id=? and status =0";
        List<LeaseFurnitureShResult> query = dbUtils.query(sql, LeaseFurnitureShResult.class, id);
        query.forEach(item->{
            item.setPcPrice(item.getPrice());
        });

        String sqls="select* from house_bill_detail where deposit_hydropower_flag = 9 and status =0 and house_bill_id =(select id from house_bill where house_lease_id =? and bill_status=3 and status =0)";
        List<HouseBillDetail> billDetails = dbUtils.query(sqls, HouseBillDetail.class, id);
        query.forEach(item->{
            List<HouseBillDetail> collect = billDetails.stream().filter(it -> it.getRentAmountCategory().equals(item.getId())).collect(Collectors.toList());
            for (int i = 0; i < collect.size(); i++) {
                HouseBillDetail houseBillDetail = collect.get(i);
                item.setPcPrice(houseBillDetail.getAmount());
                item.setSh(true);
            }
        });
        return query;
    }

    @Override
    public void add(HouseLeaseParam houseLeaseParam) {
        checkParam(houseLeaseParam,false);
        HouseLease houseLease = new HouseLease();
        BeanUtil.copyProperties(houseLeaseParam, houseLease);
        Date date = new Date();
        Long sysLoginUserId = LoginContextHolder.me().getSysLoginUserId();
        //保存入住信息
        houseLease.setStatus(0);
        houseLease.setLeaseStatus(1);
        houseLease.setCreateTime(date);
        String zqName = getZqName(houseLeaseParam);
        houseLease.setReceiptCycle(zqName);
        houseLease.setCreateUser(sysLoginUserId);
        String key = dbUtils.insertKey(houseLease).toString();
        long pkMain = Long.parseLong(key);
        houseLease.setId(pkMain);
        Long roomId = houseLeaseParam.getRoomId();
        //保存同住人信息
        List<HouseLeaseLive> leaseLiveData = houseLeaseParam.getLeaseLiveData();
        leaseLiveData.forEach(item ->{
            item.setLeaseId(pkMain);
            item.setStatus(0);
            item.setCreateTime(date);
            item.setCreateUser(sysLoginUserId);
            houseLeaseLiveService.add(item);
        });
        /**
         * 押金列表
         */
        List<RoomDeposit> yjData = houseLeaseParam.getYjData();
        LeaseDeposit  leaseDeposit =null;
        List<LeaseDeposit> leaseDepositList=new ArrayList<>();
        for (int i = 0; i < yjData.size(); i++) {
            RoomDeposit roomDeposit = yjData.get(i);
            roomDeposit.setId(null);
            roomDeposit.setStatus(0);
            leaseDeposit=new LeaseDeposit();
            BeanUtil.copyProperties(roomDeposit, leaseDeposit);
            leaseDeposit.setLeaseId(pkMain);
            leaseDeposit.setCreateTime(date);
            leaseDeposit.setCreateUser(sysLoginUserId);
            //保存租約對應的押金信息
            leaseDepositService.addEntity(leaseDeposit);
            leaseDepositList.add(leaseDeposit);
        }
        /**
         * 費用列表
         */
        List<RoomExpenses> fyData = houseLeaseParam.getFyData();
        // 租金水电是否分开收取（1 是 0不是）
        //保存租約對應的費用表
        LeaseExpenses leaseExpenses = null;
        List<LeaseExpenses> leaseExpensesList=new ArrayList<>();
        int hydropower = houseLeaseParam.getHydropower();
        for (int i = 0; i < fyData.size(); i++) {
            RoomExpenses fy = fyData.get(i);
            fy.setId(null);
            int type = fy.getType();
            if (hydropower == 0){
                fy.setYdzd(1);
            }else {
                if (type == 2){
                    fy.setYdzd(0);
                }
            }
            fy.setStatus(0);
            leaseExpenses=new LeaseExpenses();
            BeanUtil.copyProperties(fy, leaseExpenses);
            leaseExpenses.setLeaseId(pkMain);
            leaseExpenses.setCreateTime(date);
            leaseExpenses.setCreateUser(sysLoginUserId);
            leaseExpensesService.addEntity(leaseExpenses);
            leaseExpensesList.add(leaseExpenses);
        }
        /**
         * 家私列表
         */
        List<RoomFurniture> jsData = houseLeaseParam.getJsData();
        //保存租約對應的傢私表
        LeaseFurniture leaseFurniture=null;
        for (int i = 0; i < jsData.size(); i++) {
            leaseFurniture=new LeaseFurniture();
            RoomFurniture js = jsData.get(i);
            js.setId(null);
            js.setStatus(0);
            BeanUtil.copyProperties(js, leaseFurniture);
            leaseFurniture.setLeaseId(pkMain);
            leaseFurniture.setCreateTime(date);
            leaseFurniture.setCreateUser(sysLoginUserId);
            leaseFurnitureService.addEntity(leaseFurniture);
        }
        BusRoomParam roomParam=new BusRoomParam();
        roomParam.setId(houseLeaseParam.getRoomId());
        BusRoom busRoom = busRoomService.getById(roomParam);
        //基础设置
        BusBasicSettings one = busBasicSettingsService.getOne();
        //计算费用时月天数 （字典 0按固定30天算 1按月份实际天数
        int calculateStyle = one.getCalculateStyle();
        //账单金额取整 （字典 0关闭 1打开 小数点后四舍五入）
        int amount = one.getAmount();
        //保存账单信息
        // 判断水电是否分开
        int receiptYj = houseLease.getReceiptYj();
        //账单收租日日 （字典 0提前  1 固定）
        int billEndType = houseLease.getBillEndType();
        //账单收租日提前几日
        Integer billEndTqData = houseLease.getBillEndTqData();
        //账单收租日固定几月（有正负）
        Integer billEndGdmonthData = houseLease.getBillEndGdmonthData();
        //账单收租日固定几日
        Integer billEndGddayData = houseLease.getBillEndGddayData();
        int ydType = houseLeaseParam.getYdType();
        Long reservationId = houseLeaseParam.getReservationId();
        if (hydropower == 0){
            //计算账单期数
            TimeVo daysNext = CalculateQs.calculateQsNext(houseLease.getRentStartDate(), houseLease.getRentEndDate(), houseLease.getReceiptFu(), receiptYj);
            HouseBill houseBill=new HouseBill();
            houseBill.setRentStartDate(daysNext.getStart());
            houseBill.setRentEndDate(daysNext.getEnd());
            int qs = 1;
            houseBill.setBillType(2);
            houseBill.setQsnum(qs);
            houseBill.setQs("租金"+qs+"期");
            //添加账单总表
            Long billPk = addBillBysDNo("QYZDZJ",houseBill, houseLease, date, sysLoginUserId, pkMain, billEndType, billEndTqData, billEndGdmonthData, billEndGddayData);
            //添加押金明细
            addYjBillDetaillForOne(date, sysLoginUserId,leaseDepositList,billPk);
            //添加租金明细
            addZjDetailForOne(amount,houseLease.getRent(),calculateStyle,houseBill,houseLease, date, sysLoginUserId,billPk);
            //房屋押金
            if(qs == 1){
                addZjDetailForOneFwyj(houseLease, date, sysLoginUserId,billPk);
            }
            //添加水电费用明细
            addExpensesDetailForAllOne(qs,null,houseLease,DateUtil.format(houseBill.getRentedDay(),"yyyy-MM-dd"),date, sysLoginUserId,leaseExpensesList,billPk);
            if (ydType==2){
                //保存预订对冲信息
                RoomReservation reservationById = roomReservationService.getReservationById(reservationId);
                BigDecimal deposit = reservationById.getDeposit();
                reservationById.setStatus(1);
                reservationById.setUpdateUser(sysLoginUserId);
                reservationById.setUpdateTime(date);
                dbUtils.update(reservationById);
                houseBillDetailService.addYdDetail(billPk,reservationId,deposit,date,sysLoginUserId);
            }
        }else {
            //计算账单期数水电分开
            TimeVo daysNext = CalculateQs.calculateQsNext(houseLease.getRentStartDate(), houseLease.getRentEndDate(), houseLease.getReceiptFu(), receiptYj);
            HouseBill houseBill=new HouseBill();
            houseBill.setRentStartDate(daysNext.getStart());
            houseBill.setRentEndDate(daysNext.getEnd());
            int qs = 1;
            houseBill.setBillType(2);
            houseBill.setQsnum(qs);
            houseBill.setQs("租金"+qs+"期");
            Long billPk =  addBillBysDNo("QYZDZJ",houseBill,houseLease, date, sysLoginUserId, pkMain, billEndType, billEndTqData, billEndGdmonthData, billEndGddayData);
            //添加押金明细
            addYjBillDetaillForOne(date, sysLoginUserId,leaseDepositList,billPk);
            //房屋押金
            if(qs == 1){
                addZjDetailForOneFwyj(houseLease, date, sysLoginUserId,billPk);
            }
            //添加租金明细
            addZjDetailForOne(amount,houseLease.getRent(),calculateStyle,houseBill,houseLease, date, sysLoginUserId,billPk);
            //添加水电费用明细
            addExpensesDetailForAllOneByType(qs,null,houseLease,DateUtil.format(houseBill.getRentedDay(),"yyyy-MM-dd"),date, sysLoginUserId,leaseExpensesList,billPk,0);
            if (ydType==2){
                //保存预订对冲信息
                RoomReservation reservationById = roomReservationService.getReservationById(reservationId);
                BigDecimal deposit = reservationById.getDeposit();
                reservationById.setStatus(1);
                reservationById.setUpdateUser(sysLoginUserId);
                reservationById.setUpdateTime(date);
                dbUtils.update(reservationById);
                houseBillDetailService.addYdDetail(billPk,reservationId,deposit,date,sysLoginUserId);
            }
            //计算水电账单
            int hydropowercycle = houseLease.getHydropowercycle();
            TimeVo daysNextd = CalculateQs.calculateQsNext(houseLease.getRentStartDate(), houseLease.getRentEndDate(), hydropowercycle, 2);
            HouseBill houseBillsd=new HouseBill();
            houseBillsd.setRentStartDate(daysNextd.getStart());
            houseBillsd.setRentEndDate(daysNextd.getEnd());
            houseBillsd.setQsnum(qs);
            houseBillsd.setQs("水電"+qs+"期");
            houseBillsd.setBillType(3);
            Integer hydropowerBillEndType = houseLease.getHydropowerBillEndType();
            Integer hydropowerBillEndTqData = houseLease.getHydropowerBillEndTqData();
            Integer hydropowerBillEndGdmonthData = houseLease.getHydropowerBillEndGdmonthData();
            Integer hydropowerBillEndGddayData = houseLease.getHydropowerBillEndGddayData();
            Long billPkSd =  addBillBysDNo("QYZDSD",houseBillsd,houseLease, date, sysLoginUserId, pkMain, hydropowerBillEndType, hydropowerBillEndTqData, hydropowerBillEndGdmonthData, hydropowerBillEndGddayData);
            addExpensesDetailForAllOneByType(qs,null,houseLease,DateUtil.format(houseBill.getRentedDay(),"yyyy-MM-dd"),date, sysLoginUserId,leaseExpensesList,billPkSd,1);
        }
        busRoom.setLease(1);
        busRoom.setLeaseid(pkMain);
        busRoom.setUpdateTime(date);
        busRoom.setUpdateUser(sysLoginUserId);
        dbUtils.update(busRoom);
    }



    /**
     * 押金详情
     * @param date
     * @param sysLoginUserId
     * @param depositList
     * @param billPk
     */
    private void addYjBillDetaillForOne(Date date, Long sysLoginUserId, List<LeaseDeposit> depositList,Long billPk) {
        HouseBillDetail houseBillDetail = null;
        LeaseDeposit it=null;
        for (int i = 0; i < depositList.size(); i++) {
            it = depositList.get(i);
            houseBillDetail=new HouseBillDetail();
            houseBillDetail.setHouseBillId(billPk);
            int deposittype = it.getDeposittype();
            //计数计算
            if (deposittype==1){
                houseBillDetail.setAmount(DecimalUtils.multiple(it.getAmount(),it.getQuantity()));
            }else {
                houseBillDetail.setAmount(it.getAmount());
            }
            if(it.getAmount().signum()==1){//正金额
                houseBillDetail.setBillInOutType(1);
            }else {
                houseBillDetail.setBillInOutType(2);
            }
            //houseBillDetail.setBillInOutType(1);
            //押金 1  水電 2  3 （租金、4临时收入、5临时支出 6其他）
            houseBillDetail.setDepositHydropowerFlag(1);
            houseBillDetail.setRentAmountCategory(it.getId());
            houseBillDetail.setRentAmountName(it.getDepositname());
            //費用類型（字典  1抄表 0不抄表） 抄表需要
            houseBillDetail.setRentAmountType(0);
            houseBillDetail.setStatus(0);
            houseBillDetail.setCreateTime(date);
            houseBillDetail.setCreateUser(sysLoginUserId);
            houseBillDetailService.add(houseBillDetail);
        }
    }
    public void addZjDetailForOne(int amount,BigDecimal relRent,int calculateStyle,HouseBill houseBill,HouseLease houseLease, Date date, Long sysLoginUserId,
                                       Long billPk) {
        BigDecimal rent = CalculateQs.getRentMoney(amount,calculateStyle, houseLease.getReceiptFu(),
                houseLease.getReceiptYj(),houseBill.getRentStartDate(),houseBill.getRentEndDate(),
                relRent);
        HouseBillDetail houseBillDetailZj=new HouseBillDetail();
        houseBillDetailZj.setHouseBillId(billPk);
        houseBillDetailZj.setAmount(rent);
        houseBillDetailZj.setBillInOutType(1);
        //押金 1  水電 2  3 （租金、4临时收入、5临时支出）
        houseBillDetailZj.setDepositHydropowerFlag(3);
        houseBillDetailZj.setRentAmountName("租金");
        //費用類型（字典  1抄表 0不抄表） 抄表需要
        houseBillDetailZj.setRentAmountType(0);
        houseBillDetailZj.setStatus(0);
        houseBillDetailZj.setCreateTime(date);
        houseBillDetailZj.setCreateUser(sysLoginUserId);
        houseBillDetailService.add(houseBillDetailZj);
    }

    public void addZjDetailForOneFwyj(HouseLease houseLease, Date date, Long sysLoginUserId,
                                  Long billPk) {
        HouseBillDetail houseBillDetailZj=new HouseBillDetail();
        BigDecimal deposit=houseLease.getDeposit();//房屋押金
        houseBillDetailZj.setAmount(deposit);
        houseBillDetailZj.setRentAmountName("房屋押金");
        houseBillDetailZj.setDepositHydropowerFlag(1);
        houseBillDetailZj.setHouseBillId(billPk);
        houseBillDetailZj.setRentAmountType(0);
        houseBillDetailZj.setStatus(0);
        houseBillDetailZj.setCreateTime(date);
        houseBillDetailZj.setBillInOutType(1);
        houseBillDetailZj.setCreateUser(sysLoginUserId);
        houseBillDetailService.add(houseBillDetailZj);
        LeaseDeposit leaseDeposit=new LeaseDeposit();
        leaseDeposit.setAmount(deposit);
        leaseDeposit.setCreateTime(date);
        leaseDeposit.setCreateUser(sysLoginUserId);
        leaseDeposit.setDepositid(3L);
        leaseDeposit.setDepositname("房屋押金");
        leaseDeposit.setDeposittype(0);
        leaseDeposit.setLeaseId(houseLease.getId());
        leaseDeposit.setQuantity(0);
        leaseDeposit.setStatus(0);
        //保存租約對應的押金信息
        leaseDepositService.addEntity(leaseDeposit);
    }

    /**
     * 房间费用类详情
     * @param date
     * @param sysLoginUserId
     * @param expensesList
     * @param billPk
     */
    public void addExpensesDetailForAllOne(int qsNum, Long preBillId,HouseLease houseLease,String rentDay,
                                         Date date, Long sysLoginUserId, List<LeaseExpenses> expensesList, Long billPk) {
        for (int i = 0; i < expensesList.size(); i++) {
            LeaseExpenses item = expensesList.get(i);
            HouseBillDetail houseBillDetail = new HouseBillDetail();
            houseBillDetail.setHouseBillId(billPk);
            houseBillDetail.setAmount(item.getAmount());
            houseBillDetail.setBillInOutType(1);
            //押金 1  水電 2  3 租金、4临时收入、5临时支出
            houseBillDetail.setDepositHydropowerFlag(2);
            houseBillDetail.setExpensesType(item.getType());
            houseBillDetail.setRentAmountCategory(item.getId());
            houseBillDetail.setRentAmountName(item.getName());
            //費用類型（字典  1抄表 0不抄表） 抄表需要
            int type = item.getType();
            if (type == 2) {
                houseBillDetail.setRentAmountType(1);
                houseBillDetail.setAmount(new BigDecimal(0.00));
            } else {
                houseBillDetail.setRentAmountType(0);
            }
            houseBillDetail.setStatus(0);
            houseBillDetail.setCreateTime(date);
            houseBillDetail.setCreateUser(sysLoginUserId);
            Long key = houseBillDetailService.add(houseBillDetail);
            if (type == 2) {
                //保存抄表初始記錄
                HydropowerMeterParam hydropowerMeterParam=new HydropowerMeterParam();
                hydropowerMeterParam.setSolder(item.getSolder());
                hydropowerMeterParam.setAmount(item.getAmount());
                hydropowerMeterParam.setEstateRoomName(houseLease.getRoomName());
                hydropowerMeterParam.setRoomId(houseLease.getRoomId());
                hydropowerMeterParam.setReservation(houseLease.getName());
                hydropowerMeterParam.setRentedDay(rentDay);
                hydropowerMeterParam.setHouseBillId(billPk);
                hydropowerMeterParam.setLeaseId(houseLease.getId());
                hydropowerMeterParam.setCostId(item.getCostid());
                hydropowerMeterParam.setType(item.getType());
                hydropowerMeterParam.setTypeName(item.getName());

                BigDecimal bigDecimal = new BigDecimal(0.00);
                if (qsNum>1){
                    bigDecimal = hydropowerMeterService.preReading(houseLease.getId(),preBillId,item.getCostid());
                }
                hydropowerMeterParam.setPreReading(bigDecimal);
                hydropowerMeterParam.setReading(new BigDecimal(0.00));
                hydropowerMeterParam.setDosage(new BigDecimal(0.00));
                hydropowerMeterParam.setCost(new BigDecimal(0.00));
                hydropowerMeterParam.setMeterStatus("初始讀數");
                hydropowerMeterParam.setHouseBillDetailId(key);
                hydropowerMeterParam.setStatus(0);
                hydropowerMeterParam.setMeterFlag(0);
                hydropowerMeterService.add(hydropowerMeterParam);
            }
        }
    }
    /**
     * 房间费用类详情
     * @param date
     * @param sysLoginUserId
     * @param expensesList
     * @param billPk
     */
    public void addExpensesDetailForAllOneByType(int qsNum, Long preBillId,HouseLease houseLease,String rentDay,
                                            Date date, Long sysLoginUserId, List<LeaseExpenses> expensesList, Long billPk,int sdType) {
        for (int i = 0; i < expensesList.size(); i++) {
            LeaseExpenses item = expensesList.get(i);
            int type = item.getType();
            int intValue = item.getYdzd();
            // 1 抄表 0 不抄表
            if (sdType ==1 ){
                if (intValue == 1){
                    continue;
                }
            }else {
                if (intValue == 0){
                    continue;
                }
            }
            HouseBillDetail houseBillDetail = new HouseBillDetail();
            houseBillDetail.setHouseBillId(billPk);
            houseBillDetail.setAmount(item.getAmount());
            houseBillDetail.setBillInOutType(1);
            //押金 1  水電 2  3 租金、4临时收入、5临时支出
            houseBillDetail.setDepositHydropowerFlag(2);
            houseBillDetail.setExpensesType(item.getType());
            houseBillDetail.setRentAmountCategory(item.getId());
            houseBillDetail.setRentAmountName(item.getName());
            if (type == 2) {
                houseBillDetail.setRentAmountType(1);
                houseBillDetail.setAmount(new BigDecimal(0.00));
            } else {
                houseBillDetail.setRentAmountType(0);
            }
            houseBillDetail.setStatus(0);
            houseBillDetail.setCreateTime(date);
            houseBillDetail.setCreateUser(sysLoginUserId);
            Long key = houseBillDetailService.add(houseBillDetail);
            if (type == 2) {
                //保存抄表初始記錄
                HydropowerMeterParam hydropowerMeterParam=new HydropowerMeterParam();
                hydropowerMeterParam.setSolder(item.getSolder());
                hydropowerMeterParam.setAmount(item.getAmount());
                hydropowerMeterParam.setEstateRoomName(houseLease.getRoomName());
                hydropowerMeterParam.setRoomId(houseLease.getRoomId());
                hydropowerMeterParam.setReservation(houseLease.getName());
                hydropowerMeterParam.setRentedDay(rentDay);
                hydropowerMeterParam.setLeaseId(houseLease.getId());
                hydropowerMeterParam.setHouseBillId(billPk);
                hydropowerMeterParam.setCostId(item.getCostid());
                hydropowerMeterParam.setType(item.getType());
                hydropowerMeterParam.setTypeName(item.getName());
                BigDecimal bigDecimal = new BigDecimal(0.00);
                if (qsNum>1){
                    bigDecimal = hydropowerMeterService.preReading(houseLease.getId(),preBillId,item.getCostid());
                }
                hydropowerMeterParam.setPreReading(bigDecimal);
                hydropowerMeterParam.setReading(new BigDecimal(0.00));
                hydropowerMeterParam.setDosage(new BigDecimal(0.00));
                hydropowerMeterParam.setCost(new BigDecimal(0.00));
                hydropowerMeterParam.setMeterStatus("初始讀數");
                hydropowerMeterParam.setHouseBillDetailId(key);
                hydropowerMeterParam.setStatus(0);
                hydropowerMeterParam.setMeterFlag(0);
                hydropowerMeterService.add(hydropowerMeterParam);
            }
        }
    }

    @Override
    public Long addBillBysDNo(String busType,HouseBill houseBill,HouseLease houseLease,Date date,Long sysLoginUserId,
                               long pkMain,int billEndType,Integer billEndTqData,
                               Integer billEndGdmonthData,Integer billEndGddayData) {
        //保存账单明细信息
        String snowflakesId = IdFlowingUtil.getSnowflakesId(busType);
        houseBill.setHouseLeaseId(pkMain);
        houseBill.setNo(snowflakesId);
        //创建收租日期
        createRentedDay(billEndType, billEndTqData, billEndGdmonthData, billEndGddayData, houseBill);
        houseBill.setSubtotal(new BigDecimal(0.00));
        houseBill.setBillStatus(0);
        //才有效
        houseBill.setStatus(0);
        houseBill.setCreateTime(date);
        int qsnum = houseBill.getQsnum();
        houseBill.setCreateUser(sysLoginUserId);
        Long billPk = houseBillService.add(houseBill);
        houseBill.setId(billPk);
        if(qsnum==1){
            //添加第一期账单调整日志表
            BillRentAdjustmentParam billRentAdjustmentParam=new BillRentAdjustmentParam();
            billRentAdjustmentParam.setLeaseId(houseLease.getId());
            billRentAdjustmentParam.setQsNum(1);
            billRentAdjustmentParam.setName("租金1期"+DateUtil.format(houseBill.getRentStartDate(),"yyyy-MM-dd"));
            billRentAdjustmentParam.setBillDate(DateUtil.format(houseBill.getRentedDay(),"yyyy-MM-dd"));
            billRentAdjustmentParam.setAdjustType(1); // 簽約
            billRentAdjustmentParam.setAdjustStyle(1);
            billRentAdjustmentParam.setChangeMoney(new BigDecimal(0.00));
            billRentAdjustmentParam.setRent(houseLease.getRent());
            billRentAdjustmentParam.setRentStartDate(DateUtil.format(houseBill.getRentStartDate(),"yyyy-MM-dd"));
            billRentAdjustmentParam.setRentEndDate(DateUtil.format(houseBill.getRentEndDate(),"yyyy-MM-dd"));
            billRentAdjustmentService.add(billRentAdjustmentParam);
        }
        return billPk;
    }


    public  void createRentedDay(int billEndType, Integer billEndTqData, Integer billEndGdmonthData, Integer billEndGddayData, HouseBill houseBill) {
        if (billEndType==0){
            Date days = com.anti.commom.core.utils.DateUtil.addDaysResDate(DateUtil.format(houseBill.getRentStartDate(), "yyyy-MM-dd"), -billEndTqData);
            houseBill.setRentedDay(days);
            houseBill.setShouldReceiveDate(days);
        }else {
            Date daysOfMonth = getDaysOfMonth(houseBill.getRentStartDate(), billEndGdmonthData, billEndGddayData);
            houseBill.setRentedDay(daysOfMonth);
            houseBill.setShouldReceiveDate(daysOfMonth);
        }
    }


    public void delete(HouseLeaseParam houseLeaseParam) {
        String sql="delete  from house_lease where id =? ";
        dbUtils.execSql(sql,houseLeaseParam.getId());
    }

    public void edit(HouseLeaseParam houseLeaseParam) {
        HouseLease houseLease = this.queryHouseLease(houseLeaseParam);
        BeanUtil.copyProperties(houseLeaseParam, houseLease);
        dbUtils.update(houseLease);
    }

    @Override
    public void editZk(HouseLeaseParam houseLeaseParam) {
        checkBillIsTcs(houseLeaseParam.getId());
        HouseLease houseLease = this.queryHouseLease(houseLeaseParam);
        if (houseLease.getReceiptFu().intValue()!=houseLeaseParam.getReceiptFu().intValue()||houseLease.getReceiptYj().intValue()!=houseLeaseParam.getReceiptYj().intValue()){
            //重新生成当前账单周期
            HouseBill nowBill = houseBillService.getByNowBillByLeaseId(houseLease.getId(), 1);
            if (null!=nowBill&&nowBill.getQsnum()>1){
                houseBillService.delZjBillByBillId(nowBill.getId());
                //重新修改当前账单
                addNowBillZj(houseLease,houseLease.getRent(),nowBill);
                dbUtils.update(nowBill);
            }
            //刪除租金調賬記錄
            billRentAdjustmentService.deleteAdjustByIdOnEditZk(houseLease.getId(),nowBill.getQsnum());
        }
        houseLease.setName(houseLeaseParam.getName());
        houseLease.setPhone(houseLeaseParam.getPhone());
        houseLease.setIdCard(houseLeaseParam.getIdCard());
        houseLease.setIdCardImagesBack(houseLeaseParam.getIdCardImagesBack());
        houseLease.setIdCardImagesFront(houseLeaseParam.getIdCardImagesFront());
        Integer receiptFu = houseLeaseParam.getReceiptFu();
        houseLease.setReceiptFu(receiptFu);
        Integer receiptYj = houseLeaseParam.getReceiptYj();
        houseLease.setReceiptYj(receiptYj);
        Integer receiptYa = houseLease.getReceiptYa();
        houseLeaseParam.setReceiptYa(receiptYa);
        String zqName = getZqName(houseLeaseParam);
        houseLease.setReceiptCycle(zqName);
        Integer billEndType = houseLeaseParam.getBillEndType();
        houseLease.setBillEndType(billEndType);
        Integer billEndGddayData = houseLeaseParam.getBillEndGddayData();
        houseLease.setBillEndGddayData(billEndGddayData);
        Integer billEndGdmonthData = houseLeaseParam.getBillEndGdmonthData();
        houseLease.setBillEndGdmonthData(billEndGdmonthData);
        Integer billEndTqData = houseLeaseParam.getBillEndTqData();
        houseLease.setBillEndTqData(billEndTqData);
        houseLease.setRentReminderSwitch(houseLeaseParam.getRentReminderSwitch());
        houseLease.setRentReminderDay(houseLeaseParam.getRentReminderDay());
        houseLease.setRentReminderHour(houseLeaseParam.getRentReminderHour());
        houseLease.setRentReminderMinutes(houseLeaseParam.getRentReminderMinutes());
        houseLease.setRemark(houseLeaseParam.getRemark());
        Date date = new Date();
        Long sysLoginUserId = LoginContextHolder.me().getSysLoginUserId();
        houseLease.setCreateTime(date);
        houseLease.setCreateUser(sysLoginUserId);
        dbUtils.update(houseLease);
        //保存修改同住人
        List<HouseLeaseLive> leaseLiveData = houseLeaseParam.getLeaseLiveData();
        houseLeaseLiveService.deleteByLeaseId(houseLease.getId());
        leaseLiveData.forEach(item ->{
            item.setLeaseId(houseLease.getId());
            item.setStatus(0);
            item.setCreateTime(date);
            item.setCreateUser(sysLoginUserId);
            houseLeaseLiveService.add(item);
        });
        //删除结算账单
        String sql="select * from house_bill where house_lease_id =? and status=0 and bill_status=3";
        HouseBill first = dbUtils.getFirst(sql, HouseBill.class, houseLeaseParam.getId());
        if (null!=first){
            //删除账单及其详情
            houseBillService.delAllBillByBillId(first.getId());
        }
    }
    public void addNowBillZj(HouseLease lease, BigDecimal relRent,HouseBill bill){
        Date rentEndDate = lease.getRentEndDate();
        int receiptFu = lease.getReceiptFu();
        int receiptYj = lease.getReceiptYj();
        Date date = new Date();
        Long sysLoginUserId = LoginContextHolder.me().getSysLoginUserId();
        //基础设置
        BusBasicSettings one = busBasicSettingsService.getOne();
        //计算费用时月天数 （字典 0按固定30天算 1按月份实际天数
        int calculateStyle = one.getCalculateStyle();
        //账单金额取整 （字典 0关闭 1打开 小数点后四舍五入）
        int amount = one.getAmount();
        //账单收租日日 （字典 0提前  1 固定）
        int billEndType = lease.getBillEndType();
        //账单收租日提前几日
        Integer billEndTqData = lease.getBillEndTqData();
        //账单收租日固定几月（有正负）
        Integer billEndGdmonthData = lease.getBillEndGdmonthData();
        //账单收租日固定几日
        Integer billEndGddayData = lease.getBillEndGddayData();
        Date billRentEndDate = bill.getRentStartDate();
        Long billPk = bill.getId();
        TimeVo daysNext = CalculateQs.calculateQsNext(billRentEndDate,rentEndDate, receiptFu, receiptYj);
        HouseBill houseBill=new HouseBill();
        houseBill.setRentStartDate(daysNext.getStart());
        houseBill.setRentEndDate(daysNext.getStart());
        bill.setRentEndDate(houseBill.getRentEndDate());
        createRentedDay(billEndType, billEndTqData, billEndGdmonthData, billEndGddayData, houseBill);
        bill.setRentedDay(houseBill.getRentedDay());
        bill.setShouldReceiveDate(houseBill.getShouldReceiveDate());
        //添加租金明细
        addZjDetailForOne(amount,relRent,calculateStyle,houseBill,lease, date, sysLoginUserId,billPk);
    }

    @Override
    public void editFy(HouseLeaseParam2 houseLeaseParam) {
        checkBillIsTcs(houseLeaseParam.getId());
        HouseLeaseParam leaseParam=new HouseLeaseParam();
        leaseParam.setId(houseLeaseParam.getId());
        HouseLease houseLease = this.queryHouseLease(leaseParam);
        int hydropower = houseLease.getHydropower();
        Date date = new Date();
        Long sysLoginUserId = LoginContextHolder.me().getSysLoginUserId();
        if (hydropower ==1){
            houseLease.setHydropowerBillEndGddayData(houseLeaseParam.getHydropowerBillEndGddayData());
            houseLease.setHydropowerBillEndType(houseLeaseParam.getHydropowerBillEndType());
            houseLease.setHydropowerBillEndGdmonthData(houseLeaseParam.getHydropowerBillEndGdmonthData());
            houseLease.setHydropowerBillEndTqData(houseLeaseParam.getHydropowerBillEndTqData());
            houseLease.setHydropowercycle(houseLeaseParam.getHydropowercycle());
            houseLease.setHydropowerBillStart(houseLeaseParam.getHydropowerBillStart());
            houseLease.setCreateTime(date);
            houseLease.setCreateUser(sysLoginUserId);
            dbUtils.update(houseLease);
        }
        List<LeaseDeposit> yjData = houseLeaseParam.getYjData();
        String sqlYjSel="delete  from bus_lease_deposit where lease_id=?";
        Long id = houseLease.getId();
        dbUtils.execSql(sqlYjSel,id);
        yjData.forEach(im->{
            im.setLeaseId(id);
            im.setStatus(0);
            im.setCreateTime(date);
            im.setCreateUser(sysLoginUserId);
            leaseDepositService.addEntity(im);
        });
        List<LeaseExpenses> fyData = houseLeaseParam.getFyData();
        String sqlYdl="delete  from bus_lease_expenses where lease_id=?";
        dbUtils.execSql(sqlYdl,id);
        fyData.forEach(le->{
            le.setLeaseId(id);
            le.setStatus(0);
            le.setCreateTime(date);
            le.setCreateUser(sysLoginUserId);
            leaseExpensesService.addEntity(le);
        });
        HouseBill nowBill = houseBillService.getByNowBillByLeaseId(houseLease.getId(), 1);
        if (null!=nowBill&&nowBill.getQsnum()>1){
            houseBillService.delAllBillByBillId(nowBill.getId());
            addNowBill(houseLease,nowBill,fyData);
        }
        if (hydropower ==1){
            HouseBill nowBillsd = houseBillService.getByNowBillByLeaseId(houseLease.getId(), 2);
            if (null!=nowBillsd&&nowBillsd.getQsnum()>1){
                houseBillService.delAllBillByBillId(nowBillsd.getId());
                addNowBill(houseLease,nowBillsd,fyData);
            }
        }
        //删除结算账单
        String sql="select * from house_bill where house_lease_id =? and status=0 and bill_status=3";
        HouseBill first = dbUtils.getFirst(sql, HouseBill.class, houseLeaseParam.getId());
        if (null!=first){
            //删除账单及其详情
            houseBillService.delAllBillByBillId(first.getId());
        }
    }

    @Override
    public void editJs(HouseLeaseParam2 houseLeaseParam) {
        checkBillIsTcs(houseLeaseParam.getId());
        Long id = houseLeaseParam.getId();
        List<LeaseFurniture> jsData = houseLeaseParam.getJsData();
        String sql="delete from bus_lease_furniture where lease_id=?";
        dbUtils.execSql(sql,id);
        Date date = new Date();
        Long sysLoginUserId = LoginContextHolder.me().getSysLoginUserId();
        jsData.forEach(item->{
            item.setLeaseId(id);
            item.setStatus(0);
            item.setCreateTime(date);
            item.setCreateUser(sysLoginUserId);
            dbUtils.insert(item);
        });
    }

    public void addNowBill(HouseLease lease, HouseBill bill, List<LeaseExpenses> leaseExpenses){
        int hydropower = lease.getHydropower();
        Date rentEndDate = lease.getRentEndDate();
        int receiptFu = lease.getReceiptFu();
        int receiptYj = lease.getReceiptYj();
        Long pkMain = lease.getId();
        Date date = new Date();
        Long sysLoginUserId = LoginContextHolder.me().getSysLoginUserId();
        //基础设置
        BusBasicSettings one = busBasicSettingsService.getOne();
        //计算费用时月天数 （字典 0按固定30天算 1按月份实际天数
        int calculateStyle = one.getCalculateStyle();
        //账单金额取整 （字典 0关闭 1打开 小数点后四舍五入）
        int amount = one.getAmount();
        //账单收租日日 （字典 0提前  1 固定）
        int billEndType = lease.getBillEndType();
        //账单收租日提前几日
        Integer billEndTqData = lease.getBillEndTqData();
        //账单收租日固定几月（有正负）
        Integer billEndGdmonthData = lease.getBillEndGdmonthData();
        //账单收租日固定几日
        Integer billEndGddayData = lease.getBillEndGddayData();
        Date billRentEndDate = bill.getRentStartDate();
        int qsnum = bill.getQsnum();
        int billType = bill.getBillType();
        Long preBillId = bill.getId();
        if (hydropower == 0){
            TimeVo timeVo = CalculateQs.calculateQsNext(billRentEndDate, rentEndDate, receiptFu, receiptYj);
            HouseBill houseBill = new HouseBill();
            houseBill.setRentStartDate(timeVo.getStart());
            houseBill.setRentEndDate(timeVo.getEnd());
            int qs = qsnum;
            houseBill.setBillType(billType);
            houseBill.setQsnum(qs);
            houseBill.setQs("租金"+qs+"期");
            //添加账单总表
            Long billPk = addBillBysDNo("QYZDZJ",houseBill, lease, date, sysLoginUserId, pkMain, billEndType, billEndTqData, billEndGdmonthData, billEndGddayData);
            //获取调整记录
            BillRentAdjustment adjustAmountByLeaseIdOnQsNum = billRentAdjustmentService.getAdjustAmountByLeaseIdOnQsNum(lease.getId(), qs);
            BigDecimal relRent=adjustAmountByLeaseIdOnQsNum.getRent();
            //添加租金明细
            addZjDetailForOne(amount,relRent,calculateStyle,houseBill,lease, date, sysLoginUserId,billPk);
            //添加水电费用明细
            addExpensesDetailForAllOne(qs,preBillId,lease,DateUtil.format(houseBill.getRentedDay(),"yyyy-MM-dd"),date, sysLoginUserId,leaseExpenses,billPk);
        }else {
            int qs = qsnum;
            if (billType ==2) {
                //账单
                TimeVo timeVo = CalculateQs.calculateQsNext(billRentEndDate, rentEndDate, receiptFu, receiptYj);
                HouseBill houseBill = new HouseBill();
                houseBill.setRentStartDate(timeVo.getStart());
                houseBill.setRentEndDate(timeVo.getEnd());
                houseBill.setBillType(billType);
                houseBill.setQsnum(qs);
                houseBill.setQs("租金"+qs+"期");
                Long billPk =  addBillBysDNo("QYZDZJ",houseBill,lease, date, sysLoginUserId, pkMain, billEndType, billEndTqData, billEndGdmonthData, billEndGddayData);
                //获取调整记录
                BillRentAdjustment adjustAmountByLeaseIdOnQsNum = billRentAdjustmentService.getAdjustAmountByLeaseIdOnQsNum(lease.getId(), qs);
                BigDecimal relRent=adjustAmountByLeaseIdOnQsNum.getRent();
                //添加租金明细
                addZjDetailForOne(amount,relRent,calculateStyle,houseBill,lease, date, sysLoginUserId,billPk);
                //添加水电费用明细
                addExpensesDetailForAllOneByType(qs,preBillId,lease,DateUtil.format(houseBill.getRentedDay(),"yyyy-MM-dd"),date, sysLoginUserId,leaseExpenses,billPk,0);
            } else if (billType == 3){
                //计算水电账单
                int hydropowercycle = lease.getHydropowercycle();
                TimeVo timeVo = CalculateQs.calculateQsNext(billRentEndDate, rentEndDate, hydropowercycle, 2);
                HouseBill houseBillsd = new HouseBill();
                houseBillsd.setRentStartDate(timeVo.getStart());
                houseBillsd.setRentEndDate(timeVo.getEnd());
                houseBillsd.setQsnum(qs);
                houseBillsd.setQs("水電"+qs+"期");
                houseBillsd.setBillType(billType);
                Integer hydropowerBillEndType = lease.getHydropowerBillEndType();
                Integer hydropowerBillEndTqData = lease.getHydropowerBillEndTqData();
                Integer hydropowerBillEndGdmonthData = lease.getHydropowerBillEndGdmonthData();
                Integer hydropowerBillEndGddayData = lease.getHydropowerBillEndGddayData();
                Long billPkSd =  addBillBysDNo("QYZDSD",houseBillsd,lease, date, sysLoginUserId, pkMain,
                        hydropowerBillEndType, hydropowerBillEndTqData, hydropowerBillEndGdmonthData, hydropowerBillEndGddayData);
                addExpensesDetailForAllOneByType(qs,preBillId,lease,DateUtil.format(houseBillsd.getRentedDay(),"yyyy-MM-dd"),date, sysLoginUserId,leaseExpenses,billPkSd,1);
            }
        }

    }
    @Override
    public void editTzQs(HouseLeaseParam houseLeaseParam) {
        HouseLease houseLease = this.queryHouseLease(houseLeaseParam);
        //才有效
        houseLease.setLeaseStatus(2);
        houseLease.setUpdateTime(new Date());
        houseLease.setUpdateUser(LoginContextHolder.me().getSysLoginUserId());
        dbUtils.update(houseLease);
    }

    /**
     * 退租
     * @param houseLeaseParam
     */
    @Override
    public void editTuiZu(HouseLeaseTzParam houseLeaseParam) {
        checkBillIsTc(houseLeaseParam.getId());
        HouseLeaseParam lease = new HouseLeaseParam();
        Long leaseId = houseLeaseParam.getId();
        lease.setId(leaseId);
        HouseLease houseLease = this.queryHouseLease(lease);
        //3结算状态
        houseLease.setLeaseStatus(3);
        //retrieve_date
        String retrieveDate = houseLeaseParam.getRetrieveDate();
        houseLease.setRetrieveDate(DateUtil.parse(retrieveDate,"yyyy-MM-dd"));
        dbUtils.update(houseLease);
        //生成结算账单
        HouseBill houseBill = new HouseBill();
        houseBill.setBillType(2);
        houseBill.setQs("清算账单");
        //添加账单总表
        //保存账单明细信息
        String snowflakesId = IdFlowingUtil.getSnowflakesId("QYZDZJ");
        houseBill.setHouseLeaseId(leaseId);
        houseBill.setNo(snowflakesId);
        Date date = new Date();
        Long sysLoginUserId = LoginContextHolder.me().getSysLoginUserId();
        String format = DateUtil.format(date, "yyyy-MM-dd");
        DateTime parse = DateUtil.parse(format, "yyyy-MM-dd");
        //创建收租日期
        houseBill.setRentedDay(parse);
        houseBill.setShouldReceiveDate(parse);
        houseBill.setSubtotal(new BigDecimal(0.00));
        //清算状态
        houseBill.setBillStatus(3);
        //才有效
        houseBill.setStatus(0);
        houseBill.setCreateTime(date);
        houseBill.setCreateUser(sysLoginUserId);
        Long billPk = houseBillService.add(houseBill);
        houseBill.setId(billPk);
        //添加押金明细
        List<LeaseDeposit> depositList = leaseDepositService.getDepositListByLeaseId(leaseId);
        LeaseDeposit leaseDeposit=null;
        for (int i = 0; i < depositList.size(); i++) {
            leaseDeposit = depositList.get(i);
            BigDecimal negate = leaseDeposit.getAmount().negate();
            leaseDeposit.setAmount(negate);
        }
        addYjBillDetaillForOne(date, sysLoginUserId,depositList,billPk);
        //添加水电费用明细
        List<LeaseExpenses> leaseExpensesList = leaseExpensesService.getLeaseExpensesLeaseId(leaseId);
        //添加水电费用明细
        addExpensesDetailForAllOne(1,null,houseLease,format,date, sysLoginUserId,leaseExpensesList,billPk);
    }

    @Override
    public void editXuzu(HouseLeaseTzParam houseLeaseParam) {
        checkBillIsTcs(houseLeaseParam.getId());
        //删除结算账单
        String sql="select * from house_bill where house_lease_id =? and status=0 and bill_status=3";
        HouseBill first = dbUtils.getFirst(sql, HouseBill.class, houseLeaseParam.getId());
        if(first!=null){
            //删除账单及其详情
            houseBillService.delAllBillByBillId(first.getId());
        }
        //修改账单时间
        HouseLeaseParam houseLe=new HouseLeaseParam();
        houseLe.setId(houseLeaseParam.getId());
        HouseLease houseLease = getById(houseLe);
        String rentEndDate = houseLeaseParam.getRentEndDate();
        houseLease.setRentEndDate(DateUtil.parse(rentEndDate,"yyyy-MM-dd"));
        houseLease.setLeaseStatus(1);
        houseLease.setUpdateTime(new Date());
        houseLease.setUpdateUser(LoginContextHolder.me().getSysLoginUserId());
        dbUtils.update(houseLease);
    }
    void checkBillIsTcs(Long billId){
        String sql="select count(*) from house_lease where id =? and lease_status =2  and status=0 ";
        int intValue = dbUtils.getIntValue(sql, billId);
        if (intValue>0){
            throw new BusinessException(0,"該租約已退租不允许修改！");
        }
    }
    void checkBillIsTc(Long billId){
        String sql="select count(*) from house_lease where id =? and lease_status =1 and status=0 ";
        int intValue = dbUtils.getIntValue(sql, billId);
        if (intValue==0){
            throw new BusinessException(0,"該租約不允許再次退租！");
        }
    }
    @Override
    public HouseLease detail(HouseLeaseParam houseLeaseParam) {
        return this.queryHouseLease(houseLeaseParam);
    }



    @Override
    public HouseLeaseResult getIsLeaseMsgForPrint(Long id) {
        String sql="select * from house_lease where id =? ";
        HouseLeaseResult houseLeaseResult = dbUtils.get(sql, HouseLeaseResult.class, id);
        List<HouseLeaseLive> houseLeaseLives = houseLeaseLiveService.listByLeaseId(houseLeaseResult.getId());
        houseLeaseResult.setLeaseLiveData(houseLeaseLives);
        String sqldes="select a.* from bus_lease_deposit a where a.lease_id =? and a.status=0";
        List<RoomDepositResult> depositListByRoomId = dbUtils.query(sqldes, RoomDepositResult.class, id);
        for (int i = 0; i < depositListByRoomId.size(); i++) {
            depositListByRoomId.get(i).setKey(depositListByRoomId.get(i).getDepositid());
        }
        houseLeaseResult.setYjList(depositListByRoomId);
        String sqlgg="select * from bus_lease_expenses where lease_id =? and status =0";
        List<RoomExpensesResult> expensesListByRoomId = dbUtils.query(sqlgg, RoomExpensesResult.class, id);
        expensesListByRoomId.forEach(item->{
            item.setKey(item.getCostid());
        });
        houseLeaseResult.setFyList(expensesListByRoomId);
        String sqffl="select * from bus_lease_furniture where lease_id =? and status =0";
        List<RoomFurnitureResult> roomFurnitureListByRoomId = dbUtils.query(sqffl, RoomFurnitureResult.class, id);
        roomFurnitureListByRoomId.forEach(item->{
            item.setKey(item.getId()+"");
        });
        houseLeaseResult.setJsList(roomFurnitureListByRoomId);
        return houseLeaseResult;
    }

    /**
     * 获取房间租约
     *
     * @author anti
     * @date 2021-05-06 09:30:21
     */
    private HouseLease queryHouseLease(HouseLeaseParam houseLeaseParam) {
        HouseLease houseLease = this.getById(houseLeaseParam);
        if (ObjectUtil.isNull(houseLease)) {
            throw new BusinessException(HouseLeaseExceptionEnum.NOT_EXIST);
        }
        return houseLease;
    }

    private void checkParam(HouseLeaseParam houseLeaseParam, boolean isExcludeSelf){
        Long id = houseLeaseParam.getRoomId();

        //构建带name查询条件
        StringBuilder nameSb=new StringBuilder("select count(*) from bus_room where status =0 and  lease =1 and id =? ");

        //查询重复记录的数量
        int countByName = dbUtils.getIntValue(nameSb.toString(),id);

        //如果存在重复的记录，抛出异常，直接返回前端
        if (countByName >= 1) {
            throw new BusinessException(0,"該房間編號已經被签约，請重新選擇");
        }
    }
    public  static Date getDaysOfMonth(Date date,int offSetMon,int day) {
        DateTime dateTime = DateUtil.offsetMonth(date, offSetMon);
        int daysOfMonth = getDaysOfMonth(date);
        String format="";
        if (day<10){
            format = DateUtil.format(dateTime, "yyyy-MM")+"-0"+day;
        }else if (day>daysOfMonth){
            format = DateUtil.format(dateTime, "yyyy-MM")+"-"+daysOfMonth;
        }else {
            format = DateUtil.format(dateTime, "yyyy-MM")+"-"+day;
        }
        return  DateUtil.parse(format, "yyyy-MM-dd");
    }
    public  static int getDaysOfMonth(Date date) {
        Calendar calendar =Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }



    public static List<TimeVo> getMonths(int num,String startTime, String endTime) {
        // 返回的日期集合
        List<TimeVo> list=new ArrayList<>();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);
            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);
            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            getNextMonthDay(tempStart,tempEnd,num,list);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return list;
    }

    public static void getNextMonthDay(Calendar start,Calendar end,int num,List<TimeVo> list){
        Date startTime = start.getTime();
        start.add(Calendar.MONTH, num);
        start.add(Calendar.DATE, -1);
        Date startTime1 = start.getTime();
        if (start.before(end)){
            TimeVo timeVo=new TimeVo();
            timeVo.setStart(startTime);
            timeVo.setEnd(startTime1);
            start.add(Calendar.DATE, 1);
            start.getTime();
            list.add(timeVo);
            getNextMonthDay(start,end,num,list);
        }else {
            TimeVo timeVo=new TimeVo();
            timeVo.setStart(startTime);
            timeVo.setEnd(end.getTime());
            list.add(timeVo);
            return ;
        }
    }

    private static BigDecimal getBigDecimalByMonths(int calculateStyle, int receiptFu, BigDecimal rent,String startTime,String endTime) {
        List<TimeVo> months = getMonths(1, startTime,endTime );
        int size = months.size();
        int lastMonth=months.size()-1;
        TimeVo timeVo = months.get(lastMonth);
        DayCompare dayCompare = dayComparePrecise(timeVo.getStart(), timeVo.getEnd());
        //正好一个账单周期
        if (size==receiptFu){
            int ysall = dayCompare.getMonth();
            //判断最后一个月是否满足一个月
            if (ysall==1){
                //足月
                BigDecimal multiply = DecimalUtils.multiple(rent, receiptFu);
                return multiply;
            }else {
                int mothDays=30;
                if (calculateStyle!=0){
                    Date start = timeVo.getStart();
                    mothDays = com.anti.commom.core.utils.DateUtil.getCurrentMonthDayNum(start);
                }
                BigDecimal multiples = DecimalUtils.multiple(rent,(size-1));
                BigDecimal divide = DecimalUtils.divide(rent,new BigDecimal(mothDays));
                BigDecimal multiple = DecimalUtils.multiple(divide, dayCompare.getDay());
                BigDecimal add = DecimalUtils.add(multiples, multiple);
                return add;
            }
        }else {
            BigDecimal multiple = DecimalUtils.multiple(rent,(size-1));
            //不足一个账单周期
            int mothDays=30;
            if (calculateStyle!=0){
                Date start = timeVo.getStart();
                mothDays = com.anti.commom.core.utils.DateUtil.getCurrentMonthDayNum(start);
            }
            BigDecimal divide = DecimalUtils.divide(rent,new BigDecimal(mothDays));
            BigDecimal multiply = DecimalUtils.multiply(divide, new BigDecimal(dayCompare.getDay()));
            BigDecimal add = DecimalUtils.add(multiply, multiple);
            return add;
        }
    }

    private static BigDecimal getBigDecimalByYears(int calculateStyle, int receiptFu, BigDecimal rent,String startTime,String endTime) {
        //不足一个月按一个月付
        List<TimeVo> months = getMonths(1, startTime,endTime);
        int size = months.size();
        BigDecimal divide = DecimalUtils.divide(rent,new BigDecimal(12));
        BigDecimal multiply = DecimalUtils.multiple(divide, size);
        return multiply;
    }
    /**
     * 计算2个日期之间相差的  相差多少年月日
     * @param fromDate
     * @param toDate
     * @return
     */
    public static DayCompare dayComparePrecise(Date fromDate,Date toDate){
        //////////////////////////////
        int betweenDay = (int)DateUtil.betweenDay(fromDate, toDate, true)+1;
        int mothDays = com.anti.commom.core.utils.DateUtil.getCurrentMonthDayNum(fromDate);
        int betweenMonth=0;
        if (betweenDay==mothDays){
            betweenMonth=1;
        }
        return DayCompare.builder().day(betweenDay).month(betweenMonth).year(0).build();
    }


    public String getZqName(HouseLeaseParam houseLeaseParam){
        // 依据（字典 1日 2月 3年 4一次付清）
        int receiptyj = houseLeaseParam.getReceiptYj();
        // 付 （字典 付1-付18）
        int receiptfu = houseLeaseParam.getReceiptFu();
        // 押 （字典 押1-押18-自定义19）
        int receiptya = houseLeaseParam.getReceiptYa();
        if (receiptyj == 4){
            return "一次付清";
        }
        String dw="月";
        if (receiptyj == 1){
            dw="日";
        }else if (receiptyj == 2){
            dw="月";
        }else if (receiptyj == 3){
            dw="年";
        }

        if (receiptya==19){
            return "付"+receiptfu+dw+" 押金自定義";
        }
        return "付"+receiptfu+dw+" 押"+receiptya+dw;
    }
}
